<template>
  <div class="mod-config">
    <el-tree :data="menus" show-checkbox :props="defaultProps" draggable :default-expanded-keys="expandedKey"
             node-key="catId" :allow-drop="allowDrop" @node-drop="handleDrop"
             :expand-on-click-node="false">
      <span class="custom-tree-node" slot-scope="{ node, data }">
        <span>{{ node.label }}</span>
        <span>
          <el-button v-if="node.level<=2" type="text" size="mini" @click="() => append(data)">新增</el-button>
          <el-button type="text" size="mini" @click="() => edit(data)">修改</el-button>
          <el-button v-if="node.childNodes.length==0" type="text" size="mini" @click="() => remove(node, data)">
            删除
          </el-button>
        </span>
      </span>
    </el-tree>

    <!--弹出框-->
    <el-dialog :close-on-click-modal="false"
               :title='title'
               :visible.sync="dialogVisible"
               width="30%">
      <el-form :model="category">
        <el-form-item label="分类名称">
          <el-input v-model="category.name" autocomplete="off"></el-input>
        </el-form-item>
      </el-form>
      <span slot="footer" class="dialog-footer">
        <el-button @click="dialogVisible = false">取 消</el-button>
        <el-button type="primary" @click="submitData">确 定</el-button>
      </span>
    </el-dialog>
  </div>
</template>

<script>
  export default {
    data() {
      return {
        pCid: [],
        updateNodes: [],
        maxLevel: 0, // 记录最大的level层级
        title: '',
        dialogType: '', // 对话框是点击哪个打开的类型
        category: {
          name: '',
          parentCid: 0,
          catLevel: 0,
          sort: 0
        },
        dialogVisible: false,
        expandedKey: [],
        menus: [],
        defaultProps: {
          children: "children", // 子节点
          label: "name", // 显示的字段
        },
      };
    },
    watch: {},
    mounted() {
      this.getMenu();
    },
    created() {
    },
    activated() {
    },
    methods: {
      submitData() {
        if (this.dialogType == 'add') {
          this.addCategory();
        } else {
          this.editCategory();
        }
      },
      // 修改三级分类
      editCategory() {
        var {catId, name} = this.category;
        var data = {catId: catId, name: name};
        this.$http({
          url: this.$http.adornUrl('/product/category/update'),
          method: 'post',
          data: this.$http.adornData(data, false)
        }).then(({data}) => {
          this.$message({
            type: 'success',
            message: '修改成功！'
          })
          this.dialogVisible = false
          this.getMenu()
          this.expandedKey = [this.category.parentCid];
          console.log('editCategory:', this.expandedKey)
        })
      },
      // 修改三级分类对话框
      edit(data) {
        console.log('edit')
        this.dialogVisible = true
        this.dialogType = 'edit';
        this.title = '修改分类'
        this.$http({
          url: this.$http.adornUrl(`/product/category/info/${data.catId}`),
          method: 'get'
        }).then(({data}) => {
          console.log('data', data)
          this.category.name = data.category.name
          this.category.catId = data.category.catId
        })
      },
      // 添加三级分类方法
      addCategory() {
        console.log('addCategory', this.category)
        this.$http({
          url: this.$http.adornUrl('/product/category/save'),
          method: 'post',
          data: this.$http.adornData(this.category, false)
        }).then(({data}) => {
          this.$message({
            type: 'success',
            message: '保存成功！'
          })
          this.dialogVisible = false
          this.getMenu()
          this.expandedKey = [this.category.parentCid]
        })

      },
      getMenu() {
        this.$http({
          url: this.$http.adornUrl("/product/category/list/tree"),
          method: "get"
        }).then(({data}) => {
          console.log("成功！", data.data);
          this.menus = data.data;
        });
      },
      // 添加对话框
      append(data) {
        this.dialogVisible = true;
        this.dialogType = 'add';
        this.title = '添加分类'
        this.category.parentCid = data.catId;
        this.category.catLevel = data.catLevel * 1 + 1;
        console.log("append", data);
        this.category.name = ''
        this.category.catId = ''
      },

      remove(node, data) {
        console.log('data:', data)
        var ids = [data.catId]
        console.log('ids:', ids)
        this.$confirm(`确定对[ids=${ids.join(',')}]进行[${ids ? '删除' : '批量删除'}]操作?`, '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        }).then(() => {
          this.$http({
            url: this.$http.adornUrl('/product/category/delete'),
            method: 'post',
            data: this.$http.adornData(ids, false)
          }).then(({data}) => {
            this.$message({
              type: 'success',
              message: '删除成功!'
            })
            this.getMenu()
            console.log('删除成功！')
            // 默认展开
            this.expandedKey = [node.parent.data.catId]
          })
        }).catch(() => {
          this.$message({
            type: 'warn',
            message: '取消删除'
          })
        })
      },

      /**
       * 拖动节点触发事件
       * draggingNode 正在拖拽的节点
       * dropNode
       * dropType
       */
      handleDrop(draggingNode, dropNode, dropType, ev) {
        console.log('tree drop: ', draggingNode, dropNode, dropType);
        // 1.当前节点最新的父节点ID
        let pCid = 0;
        let siblings = null;
        if (dropType == 'before' && dropType == 'after') {
          pCid = dropNode.parent.data.catId == undefined ? 0 : dropNode.parent.data.catId
          siblings = dropNode.parent.childNodes
        } else {
          pCid = dropNode.data.catId
          siblings = dropNode.childNodes
        }
        // 2.当前拖拽节点的最新顺序
        for (let i = 0; i < siblings.length; i++) {
          if (siblings[i].data.catId == draggingNode.data.catId) {
            // 如果遍历的是当前拖拽的节
            let catLevel = draggingNode.level
            if (siblings[i].level != draggingNode.level) { // 如果层级不一致，说明层级发生变化
              // 当前节点层级发生变化
              catLevel = siblings[i].level;
              // 修改子节点的层级
              this.updateChildNodeLevel(siblings[i]);
            }
            this.updateNodes.push({catId: siblings[i].data.catId, sort: i, parentCid: pCid, catLevel: catLevel}) // 指定最新的父ID值
          } else {
            this.updateNodes.push({catId: siblings[i].data.catId, sort: i})
          }
        }
        // 3.当前拖拽节点最新层级
        console.log('updateNodes:', this.updateNodes)
        this.$http({
          url: this.$http.adornUrl('/product/category/updateSort'),
          method: 'post',
          data: this.$http.adornData(this.updateNodes, false)
        }).then(({data})=>{
          this.$message({
            type: 'success',
            message: '菜单顺序更新成功！'
          })
        })
        // 刷新菜单
        this.getMenu()
        this.expandedKey = [pCid]
      },

      /**
       * 递归修改子节点层级
       */
      updateChildNodeLevel(node) {
        if (node.childNodes.length > 0) {
          for (let i = 0; i < node.childNodes.length; i++) {
            var cNode = node.childNodes[i].data
            this.updateNodes.push({catId: cNode.catId, catLevel: node.childNodes[i].level})
            this.updateChildNodeLevel(node.childNodes[i]);
          }
        }
      },

      /**
       *
       * @param draggingNode 当前节点
       * @param dropNode 放到哪个节点的位置
       * @param type 放到哪个位置
       * @returns {boolean}
       */
      allowDrop(draggingNode, dropNode, type) {
        // 1.被拖动的当期节点以及所在的父节点总层数不能大于3
        // 1.1 被拖动的当前节点总层数
        console.log('88888', draggingNode, dropNode, type)
        // 统计当前节点总层数
        var level = this.countNodeLevel(draggingNode.data);
        // 当前正在拖动的节点+父节点所在的深度 不大于 3
        console.log('深度：', this.maxLevel)
        var deep = (this.maxLevel - draggingNode.data.catLevel) + 1;
        console.log('deep:', deep)
        if (type == 'inner') {
          return (deep + dropNode.level) <= 3  // 能拖动
        } else {
          return (deep + dropNode.parent.level) <= 3  // 不能拖动
        }
      },
      // 递归找到节点最大深度的节点
      countNodeLevel(node) {
        // 找到所有子节点，求出最大深度
        if (node.children != null && node.children.length > 0) {
          for (let i = 0; i < node.children.length; i++) {
            if (node.children[i].catLevel > this.maxLevel) {
              this.maxLevel = node.children[i].catLevel;
            }
            this.countNodeLevel(node.children[i]);
          }
        }
      }
    },
  };
</script>
